home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 June: Reference Library / Dev.CD Jun 99 RL Disk 1.toast / Technical Documentation / Develop / Additional Articles / Developing Symbiotic Apps / Symbiotic Samples / Symbiotic server source / Fractal Daemon / handlers.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-13  |  15.1 KB  |  620 lines  |  [TEXT/CWIE]

  1.  
  2. /* handlers.c -- AppleEvent Handlers for MANDELBROT UNIX daemon. */
  3. /* %F%  %I% */
  4.  
  5. /*
  6.  * Copyright 1993 Apple Computer, Inc.
  7.  * All Rights Reserved.
  8.  *
  9.  * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF APPLE COMPUTER, INC.
  10.  * The copyright notice above does not evidence any actual or
  11.  * intended publication of such source code.
  12.  */
  13.  
  14. /*
  15.  *    9502.16    jkc    Added offset to FillMandel() to reduce r*rows calcs
  16.  *    9502.17    jkc    Added new globals to reduce and count math operations.
  17.  *            Replaced ColToRe() and RowToIm() with macros.  Reduced
  18.  *            quantity and improved quality of debug strings.
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <sys/select.h>
  23. #include <sys/statfs.h>
  24. #include <fcntl.h>
  25. #include <sys/types.h>
  26. #include <math.h>
  27. #include "Types.h"
  28. #include "AppleEvents.h"
  29. #include "AERegistry.h"
  30. #include "AUXAESuite.h"
  31. #include "mandel.h"
  32.  
  33. typedef unsigned char BOOLEAN;
  34.  
  35. #define UNAME      "/usr/bin/uname -vr 2>&1"
  36. #define FREE(p)    if (p != NULL) free(p);
  37.  
  38. char *strcmp();
  39. char *strchr();
  40. char *strtok();
  41.  
  42. extern char *databuf;
  43. extern int errno;
  44.  
  45. /* fd_set opensocks; /* */
  46. /* char type[4];     /* */
  47. /* char creator[4];  /* */
  48.  
  49. char errorStr[1024];
  50. extern int sessionid;
  51. extern boolean pending_cmd;;
  52. extern boolean sendconfig;
  53. extern char OSVersion[32];
  54. extern char *serverVersion;
  55. extern char *clientVersion;
  56. extern boolean TimeToQuit;
  57. extern time_t time_of_last_recv;    /* last time we recvd a heartbeat */
  58. extern FILE *debugfp;
  59. extern void do_filesystem();
  60. extern struct FS_List *FS_list;
  61. extern int theInterval;
  62.  
  63.  
  64.  
  65.  
  66. OSErr HandleNullEvent (msg, reply, refcon) /* -JSM- */
  67. AppleEvent *msg;
  68. AppleEvent *reply;
  69. long refcon;
  70. {
  71. int result;
  72. DescType returnedType;
  73. Size returnedSize;
  74.  
  75. #ifdef DEBUG
  76.     fprintf(debugfp, ">>>HandleNullEvent()\n");
  77. #endif
  78.  
  79.     if (sessionid == 0)
  80.         AEGetParamPtr(msg,keySessionID,typeInteger,&returnedType,(Ptr)&sessionid,sizeof(sessionid),&returnedSize);
  81. #ifdef DEBUG
  82.             fprintf(debugfp, "sessionid   = (%d)\n", sessionid);
  83. #endif
  84.  
  85.     strcpy(errorStr,"S Success.\n");
  86.     errorStr[1]='\0';
  87.  
  88. #ifdef DEBUG
  89.             fprintf(debugfp, "errorStr   = (%s)\n", errorStr);
  90.             fprintf(debugfp, "errorStr+2 = (%s)\n", errorStr+2);
  91. #endif
  92.     result=AEPutParamPtr(reply,keyErrorNumber,typeChar,errorStr,strlen(errorStr));
  93.     result=AEPutParamPtr(reply,keyErrorString,typeChar,errorStr+2,strlen(errorStr+2));
  94.  
  95.     return (noErr);
  96. }
  97.  
  98.  
  99. OSErr HandleQuit (msg, reply, refcon) /* -JSM- */
  100. AppleEvent *msg;
  101. AppleEvent *reply;
  102. long refcon;
  103. {
  104. int result;
  105. DescType returnedType;
  106. Size returnedSize;
  107.  
  108. #ifdef DEBUG
  109.     fprintf(debugfp, ">>>HandleQuit()\n");
  110. #endif
  111.     TimeToQuit=TRUE; /* Time to die... */
  112.     return (noErr);
  113. }
  114.  
  115.  
  116. OSErr HandleHeartBeat (msg, reply, refcon) /* -JSM- */
  117. AppleEvent *msg;
  118. AppleEvent *reply;
  119. long refcon;
  120. {
  121. int result;
  122. DescType returnedType;
  123. Size returnedSize;
  124.  
  125. #ifdef DEBUG
  126.     fprintf(debugfp, ">>>HandleHeartBeat()\n");
  127. #endif
  128.  
  129.     (void)time(&time_of_last_recv);
  130.  
  131.     return (noErr);
  132. }
  133.  
  134.  
  135. OSErr HandleVersionEvent (msg, reply, refcon) /* -JSM- */
  136. AppleEvent *msg;
  137. AppleEvent *reply;
  138. long refcon;
  139. {
  140. DescType returnedType;
  141. Size returnedSize;
  142. char *p, *clientMajor, *serverMajor;
  143. char tmpdata[1024];
  144. char *tmpbuf;
  145. char *version;
  146. char *level;
  147. FILE *fp;
  148. int failcnt=0;
  149. int num;
  150. int result;
  151. OSErr retval;
  152.  
  153. #ifdef DEBUG
  154.     fprintf(debugfp, ">>>HandleVersionEvent()\n");
  155. #endif
  156.  
  157.     retval=AEGetParamPtr(msg, keyAEVersion, typeChar, &returnedType,
  158.           (Ptr)databuf, DATABUFSIZE-1, &returnedSize);
  159.     databuf[returnedSize] = '\0';
  160.  
  161.     if (retval) {
  162.     strcpy(errorStr,"F Required parameter (keyAEVersion) not found!\n");
  163.     }
  164.     else {
  165.         clientVersion = (char *)malloc(1+strlen(databuf));
  166.         strcpy(clientVersion,databuf);
  167.  
  168.  
  169.         if (strcmp(clientVersion,serverVersion) != 0) {
  170.             /* if versions are not same, look closer */
  171.         clientMajor = (char *)malloc(1+strlen(clientVersion));
  172.         serverMajor = (char *)malloc(1+strlen(serverVersion));
  173.             strcpy(clientMajor,clientVersion);
  174.         p = strchr(clientMajor,'.');
  175.         if (p != NULL) *p = '\0';
  176.             strcpy(serverMajor,serverVersion);
  177.         p = strchr(serverMajor,'.');
  178.         if (p != NULL) *p = '\0';
  179.             if (strcmp(clientVersion,serverVersion) != 0) {
  180.             /* if major versions numbers are not same... */
  181.             TimeToQuit=TRUE; /* Set global shutdown flag to shutdown server */
  182.             errorStr[0] = 'F';
  183.                 strcpy(errorStr+2,serverVersion);
  184.             }
  185.         else {
  186.             errorStr[0] = 'S';
  187.                 strcpy(errorStr+2,serverVersion);
  188.         }
  189.     
  190.             FREE(clientMajor);
  191.             FREE(serverMajor);
  192.         }
  193.         else {
  194.             errorStr[0] = 'S';
  195.             strcpy(errorStr+2,serverVersion);
  196.     }
  197.     }
  198.  
  199.     if (errorStr[0] == 'S') {
  200.     sendconfig = TRUE;
  201.         failcnt=0;
  202. uname:
  203.         if ((fp=popen(UNAME,"r")) == NULL) {
  204. #ifdef DEBUG
  205.             fprintf(debugfp,"popen() failed on command (%s)\n",UNAME);
  206.             fflush(debugfp);
  207. #endif
  208.             return(-1);
  209.         }
  210.  
  211.         tmpbuf = (char *)mymalloc(1024);
  212.         *tmpbuf = '\0';
  213.  
  214.         while ((num=read(fileno(fp),tmpdata,sizeof(tmpdata))) > 0) {
  215.             tmpbuf = strncat(tmpbuf,tmpdata,num);
  216.         }
  217.  
  218.         retval=pclose(fp);
  219.         if (retval) {
  220. #ifdef DEBUG
  221.             fprintf(debugfp,"pclose() indicates a failure from %s\n",UNAME);
  222.             fprintf(debugfp,"command returned: %s\n",tmpbuf);
  223.             fflush(debugfp);
  224. #endif
  225.             if (failcnt < 3) {
  226.         failcnt++;
  227.         sleep(1);
  228.         goto uname;
  229.         }
  230.         else {
  231. #ifdef DEBUG
  232.                 fprintf(debugfp,"Too many failures!\n");
  233.                 fflush(debugfp);
  234. #endif
  235.                 errorStr[0] = 'F';
  236.                 strcpy(errorStr+2,"\n");
  237.                 strcpy(OSVersion,"0.0");
  238.         }
  239.         }
  240.     else {
  241.         if (tmpbuf[0] != '\0') {
  242.             level=strtok(tmpbuf," \n");
  243. #ifdef DEBUG
  244.                 fprintf(debugfp,"level = (%s)\n",level);
  245.                 fflush(debugfp);
  246. #endif
  247.             version=strtok((char *)NULL," \n");
  248. #ifdef DEBUG
  249.                 fprintf(debugfp,"version = (%s)\n",version);
  250.                 fflush(debugfp);
  251. #endif
  252.             strcpy(OSVersion,version);
  253. #ifdef DEBUG
  254.                 fprintf(debugfp,"CP1\n");
  255.                 fflush(debugfp);
  256. #endif
  257.             strcat(OSVersion,".");
  258. #ifdef DEBUG
  259.                 fprintf(debugfp,"CP1\n");
  260.                 fflush(debugfp);
  261. #endif
  262.             strcat(OSVersion,level);
  263. #ifdef DEBUG
  264.                 fprintf(debugfp, "OSVersion  = (%s)\n", OSVersion);
  265.                 fflush(debugfp);
  266. #endif
  267.         }
  268.         FREE(tmpbuf);
  269.     }
  270.     }
  271.     errorStr[1] = '\0';
  272. #ifdef DEBUG
  273.             fprintf(debugfp, "errorStr   = (%s)\n", errorStr);
  274.             fprintf(debugfp, "errorStr+2 = (%s)\n", errorStr+2);
  275.             fprintf(debugfp, "OSVersion  = (%s)\n", OSVersion);
  276.             fflush(debugfp);
  277. #endif
  278.     result=AEPutParamPtr(reply,keyErrorNumber,typeChar,errorStr,strlen(errorStr));
  279.     result=AEPutParamPtr(reply,keyErrorString,typeChar,errorStr+2,strlen(errorStr+2));
  280.     result=AEPutParamPtr(reply,keyAEVersion,typeChar,OSVersion,strlen(OSVersion));
  281.  
  282.  
  283.     return (noErr);
  284. }
  285.  
  286.  
  287. OSErr HandleInterval (msg, reply, refcon) /* -JSM- */
  288. AppleEvent *msg;
  289. AppleEvent *reply;
  290. long refcon;
  291. {
  292. DescType returnedType;
  293. Size returnedSize;
  294. int exitstatus, num, result;
  295. int interval;
  296. char tmpdata[1024];
  297. FILE *fp;
  298. OSErr retval;
  299.  
  300. #ifdef DEBUG
  301.     fprintf(debugfp, ">>>HandleInterval()\n");
  302. #endif
  303.  
  304.     retval=AEGetParamPtr (msg, keyInterval, typeInteger, &returnedType,
  305.            &interval, sizeof(interval), &returnedSize);
  306.  
  307.     if (retval) {
  308.         strcpy(errorStr,"F Required parameter (keyAEInteger) not found!\n");
  309.     }
  310.     else {
  311.     theInterval = interval;
  312.         strcpy(errorStr,"S Success.\n");
  313.     }
  314.  
  315.     errorStr[1]='\0';
  316. #ifdef DEBUG
  317.             fprintf(debugfp, "errorStr   = (%s)\n", errorStr);
  318.             fprintf(debugfp, "errorStr+2 = (%s)\n", errorStr+2);
  319. #endif
  320.     result=AEPutParamPtr(reply,keyErrorNumber,typeChar,errorStr,strlen(errorStr));
  321.     result=AEPutParamPtr(reply,keyErrorString,typeChar,errorStr+2,strlen(errorStr+2));
  322.     if (retval)
  323.         return(retval);
  324.     else
  325.         return(noErr);
  326. }
  327.  
  328.  
  329. /* AE Mandelbrot server, version 2 with good divide-and-conquer technique */
  330. /* 5 Feb 92 by Mark Maxham Apple ATG/SysSoft */
  331. /* (c) 1992 Apple Computer Inc. */
  332.  
  333. extern char type[];
  334. extern char creator[];
  335.  
  336. /* globals for the divide-n-conquer routine */
  337.  
  338. double rmax, rmin, imax, imin, ipercol, rperrow;
  339. long rows, cols, maxiter;
  340. unsigned char* bytebuf;
  341. #ifdef MDEBUG
  342.   long ctrcnt, rticnt;   /* Count calls to ColToRe() and RowToIm() */
  343.   long itercnt, mndlcnt; /* Count calls to mandelbrot() and total iterations */
  344.   long mostiter;         /* Largest number of iterations used */
  345.   long boxcnt;           /* Count iterations of box optimization loops */
  346. #endif
  347.  
  348. unsigned char mandelbrot(c_r, c_i)
  349.      double c_r, c_i;
  350. {
  351.   double z_r = 0,
  352.   z_i = 0,
  353.   z_rs, z_is;
  354.   long iter = 0;
  355.  
  356. #ifdef MDEBUG
  357.   mndlcnt++;
  358. #endif
  359.   /* while (iter < 255 && |Z| < 2) (hard coding of '2' bad, FIXME) */
  360.   while (iter < maxiter && ((z_rs=z_r*z_r) + (z_is=z_i*z_i)) < 4) {
  361.     z_i = 2*z_r*z_i + c_i;
  362.     z_r = z_rs - z_is + c_r;
  363.     iter++;
  364. #ifdef MDEBUG
  365.     itercnt++;
  366. #endif
  367.   }
  368.  
  369. #ifdef MDEBUG
  370.   if (iter > mostiter)
  371.     mostiter = iter;
  372. #endif
  373.  
  374.   return (unsigned char) iter;
  375. }
  376.  
  377. /* globals for the divide-n-conquer routine used to be here */
  378.  
  379. #define RowToIm(row) (double)(row * ipercol + imin)
  380. #define ColToRe(col) (double)(col * rperrow + rmin)
  381. /*
  382. double RowToIm(row)
  383.      int row;
  384. {
  385. #ifdef MDEBUG
  386.   rticnt++;
  387. #endif
  388.   return row * ipercol + imin;
  389. }
  390.  
  391.  
  392. double ColToRe(col)
  393.      int col;
  394. {
  395. #ifdef MDEBUG
  396.   ctrcnt++;
  397. #endif
  398.   return col * rperrow + rmin;
  399. }
  400. */
  401.  
  402. void FillMandel(r1, c1, r2, c2)
  403.      int r1;
  404.      int r2; 
  405.      int c1; 
  406.      int c2; 
  407. {
  408.   unsigned char origval,  val;
  409.   int r, c, offset;
  410.   BOOLEAN same;
  411.   double re, im;
  412.  
  413.   /* I think this is a valid base case for the recursion ... */
  414.   if (r1 >= r2 || c1 >= c2)
  415.     return;
  416.   
  417.   val = origval = mandelbrot(ColToRe(c1), RowToIm(r1));
  418.   same = true;
  419.   
  420.   /* box optimization: top */
  421.   r = r1;
  422.   im = RowToIm(r);
  423.   offset = r*rows;
  424.   for (c = c1; c <= c2; c++) {
  425.     val = bytebuf[c + offset];
  426.     if (val == 0) {
  427.       re = ColToRe(c);
  428.       val = bytebuf[c + offset] = mandelbrot(re, im);
  429.     }
  430.     if (same && (val != origval))
  431.       same = false;
  432. #ifdef MDEBUG
  433.     boxcnt++;
  434. #endif
  435.   }
  436.   
  437.   /* box optimization: bottom */
  438.   r = r2;
  439.   im = RowToIm(r);
  440.   offset = r*rows;
  441.   for (c = c1; c <= c2; c++) {
  442.     val = bytebuf[c + offset];
  443.     if (val == 0) {
  444.       re = ColToRe(c);
  445.       val = bytebuf[c + offset] = mandelbrot(re, im);
  446.     }
  447.     if (same && (val != origval))
  448.       same = false;
  449. #ifdef MDEBUG
  450.     boxcnt++;
  451. #endif
  452.   }
  453.   
  454.   /* box optimization: left */
  455.   c = c1;
  456.   re = ColToRe(c);
  457.   for (r = r1; r <= r2; r++) {
  458.     offset = r*rows;
  459.     val = bytebuf[c + offset];
  460.     if (val == 0) {
  461.       im = RowToIm(r);
  462.       val = bytebuf[c + offset] = mandelbrot(re, im);
  463.     }
  464.     if (same && (val != origval))
  465.       same = false;
  466. #ifdef MDEBUG
  467.     boxcnt++;
  468. #endif
  469.   }
  470.   
  471.   /* box optimization: right */
  472.   c = c2;
  473.   re = ColToRe(c);
  474.   for (r = r1; r <= r2; r++) {
  475.     offset = r*rows;
  476.     val = bytebuf[c + offset];
  477.     if (val == 0) {
  478.       im = RowToIm(r);
  479.       val = bytebuf[c + offset] = mandelbrot(re, im);
  480.     }
  481.     if (same && (val != origval))
  482.       same = false;
  483. #ifdef MDEBUG
  484.     boxcnt++;
  485. #endif
  486.   }
  487.   
  488.   /* ah, the joys of recursion */
  489.   
  490.   if (same) {
  491.     /* All box edges have same val, so assume every point has same value */
  492.     for (r = r1+1; r <= r2-1; r++) {
  493.       offset = r*rows;
  494.       for (c = c1+1; c <= c2-1; c++)
  495.     bytebuf[c + offset] = val;
  496.     }
  497.   } 
  498.   else {
  499.     /* Subdivide box and try again */
  500.     if (r2-r1 > c2-c1) {
  501.       FillMandel(r1, c1, (r1+r2)/2, c2);
  502.       FillMandel((r1+r2)/2 + 1, c1, r2, c2);
  503.     }
  504.     else {
  505.       FillMandel(r1, c1, r2, (c1+c2)/2);
  506.       FillMandel(r1, (c1+c2)/2 + 1, r2, c2);
  507.     }
  508.   }
  509. }  /* FillMandel() */
  510.  
  511. OSErr HandleMandel(msg, reply, refcon)
  512.      AppleEvent* msg;
  513.      AppleEvent* reply;
  514.      long refcon;
  515. {
  516.   int i, j;
  517.   long rown, coln, newiter;
  518.   long servid, docid, transid;
  519.   double mag;
  520.   DescType rt;
  521.   size_t rs;
  522.   
  523. #ifdef DEBUG
  524.   long starttime, endtime;
  525.  
  526.   fprintf(debugfp, ">>>HandleMandel()\n");
  527.   fflush(debugfp);
  528. #endif
  529.  
  530.   AEGetParamPtr(msg, 'rows', 'long', &rt, &rows, sizeof(rows), &rs);
  531.   AEGetParamPtr(msg, 'cols', 'long', &rt, &cols, sizeof(cols), &rs);
  532.   AEGetParamPtr(msg, 'col#', 'long', &rt, &coln, sizeof(coln), &rs);
  533.   AEGetParamPtr(msg, 'row#', 'long', &rt, &rown, sizeof(rown), &rs);
  534.   
  535.   AEGetParamPtr(msg, 'trx#', 'long', &rt, &transid, sizeof(transid), &rs);
  536.   AEGetParamPtr(msg, 'doc#', 'long', &rt, &docid, sizeof(docid), &rs);
  537.   AEGetParamPtr(msg, 'srv#', 'long', &rt, &servid, sizeof(servid), &rs);
  538.   
  539.   AEGetParamPtr(msg, 'imin', 'doub', &rt, &imin, sizeof(imin), &rs);
  540.   AEGetParamPtr(msg, 'imax', 'doub', &rt, &imax, sizeof(imax), &rs);
  541.   AEGetParamPtr(msg, 'rmin', 'doub', &rt, &rmin, sizeof(rmin), &rs);
  542.   AEGetParamPtr(msg, 'rmax', 'doub', &rt, &rmax, sizeof(rmax), &rs);
  543.   errno = 0;
  544.   maxiter = 256*3-1;
  545.   mag = (double)cols / (rmax - rmin);
  546.   newiter = 256 * (3 + (int)log(pow(mag, 4))) - 1;
  547. #ifdef DEBUG
  548.   if (errno != 0)
  549.     fprintf(debugfp, "D'Oh! Math error occurred, %d\n", errno);
  550. #endif
  551.  
  552.   /* maxiter = newiter; */
  553.  
  554. #ifdef MDEBUG
  555.   mostiter = 0;
  556.   fprintf(debugfp,"[%d] Calculating %dx%d grid for [%d,%d] from (%.12g,%.12g) to (%.12g,%.12g) with resolution of %d\n", transid, cols, rows, coln, rown, rmin, imin, rmax, imax, maxiter);
  557.   fprintf(debugfp,"[%d] [%d, %d] ", transid, coln, rown);
  558.   fprintf(debugfp,"mag = %g, newiter = %d\n", mag, newiter);
  559.   fflush(debugfp);
  560. #endif
  561.   
  562.   AEPutParamPtr(reply, 'row#', 'long', &rown, sizeof(rown));
  563.   AEPutParamPtr(reply, 'col#', 'long', &coln, sizeof(coln));
  564.   AEPutParamPtr(reply, 'trx#', 'long', &transid, sizeof(transid));
  565.   AEPutParamPtr(reply, 'doc#', 'long', &docid, sizeof(docid));
  566.   AEPutParamPtr(reply, 'srv#', 'long', &servid, sizeof(servid));
  567.   
  568.   bytebuf = (unsigned char*) malloc(rows * cols * sizeof(unsigned char));
  569.   if (!bytebuf) {
  570. #ifdef DEBUG
  571.     fprintf(debugfp,"Panic! malloc failure of bytebuf in mandel.c\n");
  572.     fflush(debugfp);
  573. #endif
  574.   }
  575.  
  576.   ipercol = (imax - imin) / cols;
  577.   rperrow = (rmax - rmin) / rows;
  578.   for (i=0; i < rows*cols; i++)
  579.     bytebuf[i] = '\0';
  580.  
  581. #ifdef MDEBUG
  582.   /* Initialize operation counters and timer */
  583.   ctrcnt = rticnt = itercnt = mndlcnt = boxcnt = 0;
  584.   starttime = clock();
  585. #endif
  586.   FillMandel(0, 0, rows-1, cols-1);
  587.   
  588. #ifdef MDEBUG
  589.   /* Report operation counters and exec time */
  590.   endtime = clock();
  591.   fprintf(debugfp, "ColToRe() calls: %d  RowToIm() calls: %d", ctrcnt, rticnt);
  592.   fprintf(debugfp, "  mandelbrot() calls: %d  total iterations: %d", mndlcnt,
  593.       itercnt);
  594.   fprintf(debugfp, "  Box optimization loops: %d\n", boxcnt);
  595.   fprintf(debugfp, "irange = %.12g, rrange = %.12g ", (imax-imin), (rmax-rmin));
  596.   fprintf(debugfp, "Most iterations: %d\n", mostiter);
  597.   fprintf(debugfp, "CPU time: %d\n", endtime-starttime);
  598.   fflush(debugfp);
  599. #endif
  600.  
  601. #ifdef MDEBUG
  602.   if (newiter >= 37000) {
  603.     for (i=0;i<10;i++)
  604.         fprintf(debugfp, "bytebuf[%d] = %d\n",i,bytebuf[i]);
  605.     fflush(debugfp);
  606.   }
  607. #endif
  608.  
  609.   AEPutParamPtr(reply, 'data', 'TEXT', bytebuf, (size_t) rows*cols);
  610.   
  611.   free(bytebuf);
  612.   
  613. #ifdef DEBUG
  614.   fprintf(debugfp,"responding... ");
  615.   fprintf(debugfp,"done\n");
  616.   fflush(debugfp);
  617. #endif
  618.   return(noErr);
  619.